/**************************************************************************//**
 * @item     CosyOS Config
 * @file     mcucfg_cmx.c
 * @brief    CMSIS Cortex-M Core Config File
 * @author   迟凯峰
 * @version  V3.3.1
 * @date     2023.09.12
 ******************************************************************************/

#include "..\System\os_var.h"
#ifdef __MCUCFG_CMX_H

#include "..\System\os_api.h"
#include "..\System\os_iss.h"
tSP vMSP;
void *vISS[MCUCFG_ISSDEPTH];
register void **vISP __ASM("r11");
u32 vBASEPRI = 1;
#if SYSCFG_DIRMSG == __ENABLED__
u32 * volatile vDM_PSP;
#endif
#if MCUCFG_SVSTACKMONITOR == __ENABLED__
volatile u32 vISS_DepthMAX = 0;
#endif

__ASM void __isp_push(void *p)
{
	str r0, [r11,#4]!
	bx lr
}

static __ASM void *__isp_pop(void)
{
	ldr r0, [r11], #-4
	bx lr
}

void __isv_handler(void)
{
	do{
		register void *svs __ASM("r0");
		#if MCUCFG_SVSTACKMONITOR == __ENABLED__
		register u32 depth = (u32)(vISP - vISS) + 1;
		if(depth > vISS_DepthMAX)
		{
			vISS_DepthMAX = depth;
		}
		#endif
		svs = __isp_pop();
		(*vISV_Handler[*(const u8 *)svs])(svs);
	}while(vISP > vISS);
}

__ASM void __stk_pushpop(bool f, void *p)
{
__ext
	extern vTASKING;
	extern vPC;
	extern vTaskmgrBinary;
	
__INIT
	PRESERVE8
	isb
	ldr r2, =vTASKING
	cbz r0, __POP
	mrs r0, psp
	
__PC
	IF SYSCFG_TASKPCMONITOR == __ENABLED__
	ldr r3, =vTaskmgrBinary
	ldrb r3, [r3]
	cbz r3, __PUSH
	mov r3, r0
	add r3, #24
	ldmia r3, {r2}
	ldr r3, =vPC
	str r2, [r3]
	ldr r2, =vTASKING
	ENDIF
	
__PUSH
	IF MCUCFG_HARDWAREFPU == __ENABLED__
	vstmdb r0!, {s16-s31}
	ENDIF
	stmdb r0!, {r4-r10}
	ldr r3, [r2]
	str r0, [r3]
	
__POP
	str r1, [r2]
	ldr r0, [r1]
	ldmia r0!, {r4-r10}
	IF MCUCFG_HARDWAREFPU == __ENABLED__
	vldmia r0!, {s16-s31}
	ENDIF
	msr psp, r0
	
__RET
	bx lr
	nop
}

void __enter_critical(void)
{
	#if !MCUCFG_PENDSV
	__asm{msr basepri, vBASEPRI};
	__asm{dsb};
	__asm{isb};
	#else
	mPSV_Disable;
	__asm{dsb};
	__asm{isb};
	mSTK_Disable;
	__asm{dsb};
	__asm{isb};
	#endif
}

#if MCUCFG_PENDSV
void __exit_critical(void)
{
	mSTK_Enable;
	mPSV_Enable;
}
#endif

bool __enter_critical_ret(void)
{
	#if !MCUCFG_PENDSV
	__asm{msr basepri, vBASEPRI};
	__asm{dsb};
	__asm{isb};
	#else
	mPSV_Disable;
	__asm{dsb};
	__asm{isb};
	mSTK_Disable;
	__asm{dsb};
	__asm{isb};
	#endif
	return true;
}

bool __exit_critical_ret(void)
{
	#if !MCUCFG_PENDSV
	register u32 reg = 0;
	__asm{msr basepri, reg};
	#else
	mSTK_Enable;
	mPSV_Enable;
	#endif
	return true;
}

#if SYSCFG_TASKCRITICAL == __ENABLED__
void __enter_critical_rec(void)
{
	#if !MCUCFG_PENDSV
	__asm{msr basepri, vBASEPRI};
	__asm{dsb};
	__asm{isb};
	#else
	mPSV_Disable;
	__asm{dsb};
	__asm{isb};
	mSTK_Disable;
	__asm{dsb};
	__asm{isb};
	#endif
	vTaskCritical++;
}

void __exit_critical_rec(void)
{
	vTaskCritical--;
	if(!vTaskCritical)
	{
		#if !MCUCFG_PENDSV
		register u32 reg = 0;
		__asm{msr basepri, reg};
		#else
		mSTK_Enable;
		mPSV_Enable;
		#endif
	}
}
#endif

uint32_t os_masking_pri(uint32_t pri)
{
	register uint32_t pre;
	pri <<= vBASEPRI;
	__asm{mrs pre, basepri};
	__asm{msr basepri_max, pri};
	__asm{dsb};
	__asm{isb};
	return pre;
}

void __mi_task_scheduler(void)
{
	vScheduling_f = true;
	mPSV_Trigger;
}

void __mu_task_scheduler(void)
{
	mEnterCritical;
	vScheduling_f = true;
	mPSV_Trigger;
	mExitCritical;
	while(vScheduling_f);
}

#endif
